#ifndef XLCOMM_BASE_LOGSTREAM_H_
#define XLCOMM_BASE_LOGSTREAM_H_

#include <stdio.h>

#include <string>

#include "xlcomm/base/fix_buffer.h"
#include "xlcomm/define.h"
#include "xlcomm/noncopyable.h"

namespace xlcomm {

// 日志流类
class XLCOMM_API LogStream : noncopyable {
 public:
  using Buffer = FixBuffer<kSmallBufferSize>;

  LogStream() {}
  ~LogStream() {}

  LogStream& operator<<(const char* str) {
    if (str) {
      buffer_.Append(str, strlen(str));
    } else {
      buffer_.Append("(nullptr)", 9);
    }
    return *this;
  }

  LogStream& operator<<(const unsigned char* str) {
    return operator<<(reinterpret_cast<const char*>(str));
  }

  LogStream& operator<<(const std::string& str) {
    buffer_.Append(str.c_str(), str.length());
    return *this;
  }

  LogStream& operator<<(char ch) {
    buffer_.Append(&ch, 1);
    return *this;
  }

  LogStream& operator<<(unsigned char ch) {
    return operator<<(static_cast<char>(ch));
  }

  LogStream& operator<<(short n) {
    FormatInteger(n);
    return *this;
  }

  LogStream& operator<<(unsigned short n) {
    FormatInteger(n);
    return *this;
  }

  LogStream& operator<<(int n) {
    FormatInteger(n);
    return *this;
  }

  LogStream& operator<<(unsigned int n) {
    FormatInteger(n);
    return *this;
  }

  LogStream& operator<<(long n) {
    FormatInteger(n);
    return *this;
  }

  LogStream& operator<<(unsigned long n) {
    FormatInteger(n);
    return *this;
  }

  LogStream& operator<<(long long n) {
    FormatInteger(n);
    return *this;
  }

  LogStream& operator<<(unsigned long long n) {
    char str[32];
    snprintf(str, sizeof(str), "%llu", n);
    buffer_.Append(str, strlen(str));
    return *this;
  }

  LogStream& operator<<(const void* ptr) {
    char str[32];
    snprintf(str, sizeof(str), "%p", ptr);
    buffer_.Append(str, strlen(str));
    return *this;
  }

  // 获取buffer的引用
  const Buffer& buffer() const { return buffer_; }

 private:
  // 格式化整型
  template <typename INT>
  void FormatInteger(INT n) {
    char str[32];
    snprintf(str, sizeof(str), "%lld", static_cast<long long>(n));
    buffer_.Append(str, strlen(str));
  }

  Buffer buffer_;
};

}  // namespace xlcomm

#endif  // XLCOMM_BASE_LOGSTREAM_H_